Common execution environment in server-side and remote scripts (a)
Ability to upload a new script (b)
Ability to "reference" the script from an external location (c)
Execute scripts as alert notifications (d)
Ability to upload a new script while creating the alert definition/template (e)
Ability to edit the script assigned to the alert (f)
Execute scripts in other parts of the RHQ UI - TBD
Our current content subsystem will be used for storing the scripts. This will enable us to reuse the existing infrastructure and content plugins as well as automatically gain new functionality in the future when new content plugins become available to pull the scripts from remote locations.
There is one fundamental difference between the content subsystem as it stands today and what we need for the CLI alerts to make sense. Today, the content subsystem is tightly coupled with the resource types because it was designed to deliver updates to the contents for different resources. Because the CLI scripts used as alert notifications have no conceptual counter-part on the agent-side, we need to break this coupling.
Fortunately, this doesn't seem to be too complicated (tests pending). In the content subsystem, there is a concept of package type that distinguishes different packages by "type" (which is defined by the agent plugins) and that also ties that type to a particular resource type. By allowing the resource type to be null (and update the existing code to take that possibility into account), we can effectively allow for package types not tied to a resource type. Such package types would be declared on the server side using the new packagetype server plugins.
This is all we need to store the scripts in the content subsystem. The user will be able to select scripts from existing repos (c) as long as those repos contain packages of the "server-side CLI script" package type (which is defined by another serverside plugin) and there will be a possibility to upload a script during alert def creation (e). Such script will be stored as a package in the configured repo.
The security concerns around uploading "stuff" to repositories are discussed in a separate document.
(a) Current remoting CLI defines an execution environment - predefined variables in the script's scope. To the extent it makes sense the same environment should be available to the scripts being executed on the server.
The following variable are available to the scripts in the remote client:
unlimitedPC - an unlimited page control
pageControl - another page control, not really sure about the difference
exporter - an object used to export the data into a file using the TabularWriter
subject - the currently logged in user
pretty - the pretty printer
scriptUtil - script utility methods
ProxyFactory - provides a proxied view on a resource (i.e. operations exposed as object's methods, etc.)
Assert - assertion utilities
configurationEditor - provides an interactive configuration editor
rhq - provides login and logout methods
Apart from the above variables, all the remote interfaces existing in RHQ are exposed as variables like this:
ResourceManagerRemote interface is present as ResourceManager variable, etc.
Additionally, all the methods of scriptUtil, Assert, configurationEditor and rhq objects are also available as "global" methods that call the appropriate methods on the objects themselves. The ProxyFactory exposes the editPluginConfiguration() and editResourceConfiguration() methods on the resource proxies that provide the interactive editing of the configuration.
Above all of that, the user is able to execute "commands" on the CLI commandline that are not javascript based:
login
logout
help
exec
record
quit
version
In the server environment, the interactive parts of the above don't make sense and thus won't be available in the script scope. The script running on the server is going to be provided with a subject it is authenticated with so providing login and logout methods using the rhq variable doesn't make sense.
On the server, therefore, the following environment will be available in the scripts:
unlimitedPC - an unlimited page control
pageControl - another page control, not really sure about the difference
exporter - an object used to export the data into a file using the TabularWriter
subject - the currently logged in user (i.e. the user executing the script on the server)
pretty - the pretty printer
scriptUtil - script utility methods
ProxyFactory - provides a proxied view on a resource (i.e. operations exposed as object's methods, etc.)
Assert - assertion utilities
all the interfaces of the RemoteAPI
On the serverside there will be no support for the "commands" (exec, help and the like) because the server-side script is not interactive.
The scripts should run in a sandboxed environment that would disallow the most dangerous operations, namely System.exit(). The current set of permissions allowed for the scripts is defined in StandardScriptPermissions.java.
With the script storage sorted, the alert notifications suddenly become quite simple.
The alert notification is going to be implemented as a new server-side alert plugin. Upon the firing of the alert, the notification is going to instantiate a scripting engine and execute the associated script (d).
The script is going to be provided with the standard bindings as defined above + the actual alert being triggered under a variable surprisingly called alert.
The alert definitions is going to require a custom UI using which a user will be able to pick the appropriate script from some repo. The UI is also going to provide a way to upload a new script directly within the alert notification definition.
For the first iteration, the support for in-line editing of the scripts inside the alert definition isn't planned because we'd have to have some logic around the possibility of two alert defs using the same script overwriting the changes made by the other. The usual workflow for the alert scripts should be to develop -> test in remote CLI -> use in an alert notification, so supporting inline edits could encourage users to make untested edits. This feature, although cool, isn't therefore considered as important (f).
The alert notification will always execute the "latest" version of the package. The latest version is going to be determined by the package type plugin with a default fallback that uses OSGi version comparator to compare the versions or the file create date if the version string is not available on the package version.
During the creation of the alert definition, the user will be able to set the user the script should run as. The user can either pick him/herself or another user provided he can successfully authenticate as that user (obviously there is going to be a custom UI for this).
When a user is deleted the alerts that should be run with his/her privileges will fail with an error message describing the reason. The RHQ administrator will be provided with the plugin defined "controls" to check for such misconfigured alert definitions as well as re-assigning them to different users.
The simplest way (and the only reasonable) is to follow the example of referencing the users in the histories. For users we don't actually store a user ID but rather only his/her username exactly to prevent constraint violations when deleting a user. As with other alert senders, the alert notification log entry will be created from the sender result object that contains the summary and success or failure message. The CLI alert sender will include information about the repo, package and its version that it used to fire the alert in its summary and script output or exception stacktrace in its success or failure message respectively.